#pragma once
#include <cstdio>
#include <cstdlib>
#include "glad/glad.h"

class RgbTexture{
public:
    RgbTexture() = delete;
    ~RgbTexture(){
        free(data);
    }
    explicit RgbTexture(const std::string &path, uint32_t width, uint32_t height){
        this->width = width;
        this->height = height;
        this->frameSize = width * height * 3;
        this->currentFrameIndex = 0;

        FILE *fp;
        if ((fp=fopen(path.c_str(),"rb")) != nullptr){
            fseek(fp, 0, SEEK_END);
            dataSize = ftell(fp);
            this->data = static_cast<uint8_t *>(malloc(sizeof(uint8_t) * dataSize));
            fseek(fp, 0, SEEK_SET);
            fread(data, 1, dataSize, fp);
            fclose(fp);
            fp = nullptr;
        } else {
            printf("Can not open file: %s\n", path.c_str());
        }

        this->totalFrameCount = dataSize / frameSize;

        glGenTextures(1, &texYId);
        glBindTexture(GL_TEXTURE_2D, texYId);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        // first frame
        updateTexture();
    }

    void updateTexture(){
        if(currentFrameIndex >= 0 && currentFrameIndex < totalFrameCount){
            uint8_t *buffer = data + currentFrameIndex * frameSize;
            glBindTexture(GL_TEXTURE_2D, texYId);
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);
            glBindTexture(GL_TEXTURE_2D, 0);
        } else {
            currentFrameIndex = 0;
        }
    }

    void nextFrame(){
        currentFrameIndex++;
        updateTexture();
    }

    void preFrame(){
        currentFrameIndex--;
        updateTexture();
    }

    void destroy(){
        glDeleteTextures(1, &texYId);
    }

    uint32_t width, height;
    uint32_t frameSize;
    int currentFrameIndex;
    int totalFrameCount;

    size_t dataSize;
    uint8_t *data;

    GLuint texYId{};
};